














#import "YHIAPManager.h"
#import <StoreKit/StoreKit.h>


@interface YHIAPManager () <SKPaymentTransactionObserver, SKProductsRequestDelegate>
@property (nonatomic, copy) YHIAPCompletionHandle completionHandle;
@property (nonatomic, copy) NSString *productId;
@property (nonatomic, copy) NSString *orderId;
@end


@implementation YHIAPManager

+ (YHIAPManager *)sharedInstance {
    static YHIAPManager *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[YHIAPManager alloc] init];
    });
    return sharedInstance;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    }
    return self;
}

- (void)dealloc {
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

#pragma mark - 开始购买
- (void)startPurchaseWithProductId:(NSString *)productId
                           orderId:(NSString *)orderId
                    completeHandle:(YHIAPCompletionHandle)completeHandle {
    [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
    if (productId) {
        if ([SKPaymentQueue canMakePayments]) {
            self.productId = productId;
            self.completionHandle = completeHandle;
            self.orderId = orderId;
            SKMutablePayment *payment = [[SKMutablePayment alloc] init];
            payment.applicationUsername = orderId;
            payment.productIdentifier = productId;
            payment.quantity = 1;
            [[SKPaymentQueue defaultQueue] addPayment:payment];
        } else {
            [self handleActionWithType:IAPPurchNotArrow data:nil];
        }
    }
}

#pragma mark - 回调
- (void)handleActionWithType:(YHIAPPurchType)type data:(NSData *)data {
    switch (type) {
        case IAPPurchSuccess:
            NSLog(@"购买成功");
            break;
        case IAPPurchFailed:
            NSLog(@"购买失败");
            break;
        case IAPPurchCancel:
            NSLog(@"用户取消购买");
            break;
        case IAPPurchVerFailed:
            NSLog(@"订单校验失败");
            break;
        case IAPPurchVerSuccess:
            NSLog(@"订单校验成功");
            break;
        case IAPPurchNotArrow:
            NSLog(@"不允许程序内付费");
            break;
        default:
            break;
    }
    if (self.completionHandle) {
        self.completionHandle(type, data);
    }
}

#pragma mark - 交易成功验证
- (void)verifyPurchaseWithPaymentTransaction:(SKPaymentTransaction *)transaction {
    NSString *orderNo = transaction.payment.applicationUsername;
    NSString *productId = [NSString xm_stringNoNullWith:transaction.payment.productIdentifier];
    NSString *transactionId = [NSString xm_stringNoNullWith:transaction.transactionIdentifier];
    NSURL *recepitURL = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData *receiptData = [NSData dataWithContentsOfURL:recepitURL];
    NSString *receiptString = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    if (!receiptData) {
        [self handleActionWithType:IAPPurchVerFailed data:nil];
        return;
    }
    
    NSMutableDictionary *paramDic = @{
        @"order_sn": [NSString xm_stringNoNullWith:orderNo],
        @"receipt_data": [NSString xm_stringNoNullWith:[receiptString stringByURLEncode]],
        @"product_id": [NSString xm_stringNoNullWith:productId],
        @"transaction_id": [NSString xm_stringNoNullWith:transactionId]
    }.mutableCopy;
    
    [[YHNetworkManager sharedInstance] postWithUrl:@"api/money/appstoreNotify"
                                        parameters:paramDic
                                     completeBlock:^(XMResponseTip * _Nonnull tip, id  _Nullable result) {
        
        if (tip.success) {
            if ([result objectForKey:@"transaction"]) {
                NSArray *array = [result safe_objectForKey:@"transaction"];
                NSLog(@"array: %@", array);
                if (array.count > 0) {
                    NSArray *transactions = [SKPaymentQueue defaultQueue].transactions;
                    NSLog(@"transactions: %@ ", transactions);
                    for (SKPaymentTransaction *obj in transactions) {
                        NSLog(@"transactionIdentifier: %@", obj.transactionIdentifier);
                        if ([array containsObject:obj.transactionIdentifier]) {
                            [[SKPaymentQueue defaultQueue] finishTransaction:obj];
                        }
                    }
                }
            }
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            [self handleActionWithType:IAPPurchVerSuccess data:receiptData];
        } else {
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self reVerify1:transaction];
            });
        }
        
    }];
    
}

- (void)reVerify1:(SKPaymentTransaction *)transaction {
    NSString *orderNo = transaction.payment.applicationUsername;
    NSString *productId = [NSString xm_stringNoNullWith:transaction.payment.productIdentifier];
    NSString *transactionId = [NSString xm_stringNoNullWith:transaction.transactionIdentifier];
    NSURL *lanuch = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData *reponse = [NSData dataWithContentsOfURL:lanuch];
    NSString *sharetrace = [reponse base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    
    if (!reponse) {
        [self handleActionWithType:IAPPurchVerFailed data:nil];
        return;
    }
    
    NSMutableDictionary *paramDic = @{
        @"order_sn": [NSString xm_stringNoNullWith:orderNo],
        @"receipt_data": [NSString xm_stringNoNullWith:[sharetrace stringByURLEncode]],
        @"product_id": [NSString xm_stringNoNullWith:productId],
        @"transaction_id": [NSString xm_stringNoNullWith:transactionId]
    }.mutableCopy;
    
    [[YHNetworkManager sharedInstance] postWithUrl:@"api/money/appstoreNotify"
                                        parameters:paramDic
                                     completeBlock:^(XMResponseTip * _Nonnull tip, id  _Nullable result) {
        
        if (tip.success) {
            if ([result objectForKey:@"transaction"]) {
                NSArray *array = [result safe_objectForKey:@"transaction"];
                if (array.count > 0) {
                    NSArray *transactions = [SKPaymentQueue defaultQueue].transactions;
                    for (SKPaymentTransaction *obj in transactions) {
                        NSLog(@"transactionIdentifier: %@", obj.transactionIdentifier);
                        if ([array containsObject:obj.transactionIdentifier]) {
                            [[SKPaymentQueue defaultQueue] finishTransaction:obj];
                        }
                    }
                }
            }
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            [self handleActionWithType:IAPPurchVerSuccess data:reponse];
        } else {
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self reVerify2:transaction];
            });
        }
        
    }];
    
    
}


- (void)reVerify2:(SKPaymentTransaction *)transaction {
    NSString *orderNo = transaction.payment.applicationUsername;
    
    NSString *productId = [NSString xm_stringNoNullWith:transaction.payment.productIdentifier];
    
    NSString *transactionId = [NSString xm_stringNoNullWith:transaction.transactionIdentifier];
    
    NSURL *lanuch = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData *reponse = [NSData dataWithContentsOfURL:lanuch];
    NSString *sharetrace = [reponse base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    
    if (!reponse) {
        [self handleActionWithType:IAPPurchVerFailed data:nil];
        return;
    }
    
    
    
    NSMutableDictionary *paramDic = @{
        @"order_sn": [NSString xm_stringNoNullWith:orderNo],
        @"receipt_data": [NSString xm_stringNoNullWith:[sharetrace stringByURLEncode]],
        @"product_id": [NSString xm_stringNoNullWith:productId],
        @"transaction_id": [NSString xm_stringNoNullWith:transactionId]
    }.mutableCopy;
    
    [[YHNetworkManager sharedInstance] postWithUrl:@"api/money/appstoreNotify"
                                        parameters:paramDic
                                     completeBlock:^(XMResponseTip * _Nonnull tip, id  _Nullable result) {
        if (tip.success) {
            if ([result objectForKey:@"transaction"]) {
                NSArray *array = [result safe_objectForKey:@"transaction"];
                NSLog(@"array: %@", array);
                if (array.count > 0) {
                    NSArray *transactions = [SKPaymentQueue defaultQueue].transactions;
                    NSLog(@"transactions: %@", transactions);
                    for (SKPaymentTransaction *obj in transactions) {
                        NSLog(@"transactionIdentifier: %@", obj.transactionIdentifier);
                        if ([array containsObject:obj.transactionIdentifier]) {
                            [[SKPaymentQueue defaultQueue] finishTransaction:obj];
                        }
                    }
                }
            }
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            [self handleActionWithType:IAPPurchVerSuccess data:reponse];
        } else {
            [self handleActionWithType:IAPPurchVerFailed data:reponse];
        }
        
    }];
}

#pragma mark - SKProductsRequestDelegate
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
    NSArray *product = response.products;
    if ([product count] <= 0) {
        return;
    }
    
    SKProduct *p = nil;
    for (SKProduct *pro in product) {
        if ([pro.productIdentifier isEqualToString:self.productId]) {
            p = pro;
            break;
        }
    }
    
    SKPayment *payment = [SKPayment paymentWithProduct:p];
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

#pragma mark - 请求失败
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
    NSLog(@"从App Store中检索关于指定产品列表的本地化信息错误-----------------:%@", error);
}

- (void)requestDidFinish:(SKRequest *)request {
    NSLog(@"requestDidFinish");
}

#pragma mark - SKPaymentTransactionObserver
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions {
    for (SKPaymentTransaction *transaction in transactions) {
        switch (transaction.transactionState) {
            case SKPaymentTransactionStatePurchased:
                NSLog(@"【支付结果】======= 交易成功");
                [self verifyPurchaseWithPaymentTransaction:transaction];
                break;
            case SKPaymentTransactionStatePurchasing:
                NSLog(@"【支付结果】======= 商品添加进列表");
                break;
            case SKPaymentTransactionStateRestored:
                NSLog(@"【支付结果】======= 已购买过该商品");
                [self handleActionWithType:IAPPurchRestored data:nil];
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                break;
            case SKPaymentTransactionStateFailed:
                NSLog(@"【支付结果】======= 交易失败");
                if (transaction.error.code != SKErrorPaymentCancelled) {
                    [self handleActionWithType:IAPPurchFailed data:nil];
                } else {
                    [self handleActionWithType:IAPPurchCancel data:nil];
                }
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                break;
            default:
                break;
        }
    }
}



- (void)localReceiptVerifyingWithUrl:(NSString *)requestUrl
                          receiptStr:(NSString *)receiptStr
                         transaction:(SKPaymentTransaction *)transaction {
    NSDictionary *requestContents = @{
        @"receipt-data": receiptStr,
    };
    NSError *error;
    
    
    
    NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                          options:0
                                                            error:&error];
    NSString *verifyUrlString = requestUrl;
    NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:[[NSURL alloc] initWithString:verifyUrlString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];
    [storeRequest setHTTPMethod:@"POST"];
    [storeRequest setHTTPBody:requestData];
    
    
    
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:storeRequest
                                            completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
        if (error) {
            NSLog(@"链接失败");
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
        } else {
            NSError *error;
            NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
            if (!jsonResponse) {
                NSLog(@"验证失败");
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            }
            NSLog(@"验证成功");
            
            
            
        }
    }];
    [task resume];
}


@end
